package com.boot.security.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollectionUtil;
import com.boot.security.model.bo.TokenAuthentication;
import com.boot.web.http.HttpModel;
import com.boot.web.util.HttpResponseUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.security.KeyPair;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 霜寒 <1621856595@qq.com>
 * @description Web安全接口
 * @date 2020/2/15 20:56
 **/
@Slf4j
@RestController
@RequestMapping("/security")
@Api("安全接口")
public class SecurityController {

    @Autowired
    KeyPair keyPair;

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 获取公钥
     * @date 2020/3/8 15:32
     **/
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @GetMapping("/key")
    @ApiOperation(value = "获取公钥")
    public ResponseEntity<HttpModel<Object>> publicKey() {
        return HttpResponseUtil.OK("获取公钥成功", Base64.encode(keyPair.getPublic().getEncoded()));
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 验证当前用户是否已登录
     * @date 2020/3/8 15:29
     **/
    @PostMapping("/authentication")
    @ApiOperation(value = "验证当前用户是否已登录")
    public ResponseEntity<HttpModel<Object>> authentication() {
        // AuthenticationFilter 已经验证过了
        return HttpResponseUtil.OK("用户已登录");
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 验证当前用户是否有某些权限
     * @date 2020/3/8 15:30
     **/
    @PostMapping("/authorization")
    @ApiOperation(value = "验证当前用户是否有某些权限")
    @ApiImplicitParam(name = "resourceAuthorities", value = "权限列表", required = true, paramType = "body", dataTypeClass = List.class)
    public ResponseEntity<HttpModel<Object>> authorization(@RequestBody Set<String> resourceAuthorities) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication instanceof TokenAuthentication) {
            Set<String> userAuthorities = authentication.getAuthorities().stream()
                    .map(GrantedAuthority::getAuthority)
                    .collect(Collectors.toSet());
            if (CollectionUtil.containsAll(userAuthorities, resourceAuthorities)) {
                return HttpResponseUtil.OK("用户权限校验通过");
            } else {
                Collection<String> intersection = CollectionUtil.intersection(userAuthorities, resourceAuthorities);
                Collection<String> disjunction = CollectionUtil.disjunction(resourceAuthorities, intersection);
                return HttpResponseUtil.forbidden(String.format("%s 缺少权限: %s",
                        authentication.getName(),
                        disjunction.toString()));
            }
        } else {
            throw new AuthenticationServiceException(String.format("Authentication 仅支持 %s",
                    TokenAuthentication.class.getSimpleName()));
        }
    }

}
